-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CS2] Support await
in REPL without wrapper function
#4604
Conversation
How come you could implement this so easily, while nodejs/node#13209 is still open? Some kind of backwards compatibility thing? What am I missing? |
Interesting... it seems a lot in that thread is to do with ambiguity with One thing I didn't think about that came up in the thread is what should happen if the user ctrl+c's an awaiting promise. The way this is implemented right now, if the promise hangs forever there is no observable issue (same as doing That said, with some acrobatics it should be possible to intercept the |
await
in REPL without wrapper functionawait
in REPL without wrapper function
@AlvaroBernalG do you want to have a play with this branch and see if it works as you'd hoped? |
@connec I have been playing with your branch and the only thing that I found is that I am unable to assign the result of an await to a variable. Which useful in cases when you want to comfortably inspect the element returned. @princejwesley has a gist where he solve a similar problem by appending the assignment variable to So if you have an await whose result is being assigned to a variable like so: coffee>myVariableResult = await wiki().page('batman') It would get transpiled into: // `(async() => global.${myVariableResult}=${awaitExpression})()`
(async() => global.myVariableResult = await wiki().page('batman'))() if there is no variable assignment then: // `(async() => ${awaitExpression})()`
(async() => await wiki().page('batman'))() |
@AlvaroBernalG Good example. That's certainly unexpected behavior. |
Good catch indeed, didn't think about assignment. I suppose I need to update the Just to be clear, the second example ("if there is no variable assignment") is working as expected? |
@connec I confirm that besides that everything is working as expected ( Even canceling the promise before it finish with ctrl +c .. which is awesome :) ) |
I found a much more robust approach that also supports console.log await Promise.resolve 1
# and assignment, of course :)
foo = await Promise.resolve 1 About the cancelling... that's actually a bit weird, and I don't think there's anything we can easily do about it. For example, running the following in the REPL will result in foo = await new Promise (resolve) -> setTimeout (-> resolve 1), 5000
# ^C
foo = 2
# wait a few seconds...
_
# undefined
foo
# 1 This is because it's impossible to actually cancel a native promise. That said, in its current form it's useful for playing with promise libraries, and the same problem would exist in manual usage: foo = null
(new Promise (resolve) -> setTimeout (-> resolve 1), 5000).then (result) -> foo = result
foo = 2
# wait a few seconds
foo
# 1 Let me know if this works better for you @AlvaroBernalG 😄 |
Rather than compiling top-level await expressions directly, which will always throw a syntax error, the REPL wrapper will now wrap them in a closure and handle the returned promise before calling back to the REPL. Fixes #4603.
This change allows users to 'cancel' awaited expressions that they don't want to see the result of. Ultimately, this *does not* prevent the expression from completing (e.g. for `await fetch(url)`, `url` will still be downloaded, but the user won't have to wait for it to finish and the result won't be printed).
@AlvaroBernalG can you please confirm that this PR works as expected? @lydell, any notes or is this ready to merge? |
I haven't tested it, but the code looks good. |
@connec @GeoffreyBooth Apologies for the delay. For some reason I missed the emails and warnings on Github. I tested the branch and I can confirm that it is working as expected. @connec Thank you very much. Coffeescript REPL is now my default REPL. Once again apologies for the delay. |
Great, thanks! |
Glad it's working out for you @AlvaroBernalG 😄 |
I went ahead and made a fix for #4603 because I think it could be a really useful feature for playing with promise libraries.
I took care to ensure non-await evaluations will still happen fully synchronously (e.g.
process.nextTick -> console.log 'async'
works as before).I didn't write any tests, because putting them in
test/repl.coffee
ortest/async.coffee
would involve quite a bit of copypasta. I did think of making the async test globally available (e.g. astest.async
ortestAsync
) but that was a bigger change than I'd planned to make. If someone has an opinion on how to deal with it I'm happy to add some tests.Rather than compiling top-level await expressions directly, which will
always throw a syntax error, the REPL wrapper will now wrap them in a
closure and handle the returned promise before calling back to the REPL.
Fixes #4603.